Popular Searches
Popular Course Categories
Popular Courses

Understanding the useState Hook

Understanding the useState Hook

State Management with useState

Understanding the useState Hook in React JS

Topic: Understanding the useState Hook

Technology: React JS

React JS Training: JustAcademy React JS Training Course

Course Demo: Register for React JS Course Demo


1. Introduction to the useState Hook

The useState Hook is a built-in React function that allows functional components to store, manage, and update information over time. It helps create interactive user interfaces that respond to user actions such as clicking buttons, entering text, selecting options, and submitting forms.

When a state setter is called, React schedules an update and renders the component again when necessary so the interface can display the updated state.

For example, a counter application can use useState to remember the current count and update it whenever a user clicks the Increase button.

Example

import { useState } from "react";
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={() => setCount(count + 1)}>
        Increase
      </button>
    </div>
  );
}
export default Counter;

Explanation: The count variable stores the current count, setCount requests an update, and useState initializes the count to 0.


2. What Is a React Hook?

A Hook is a special React function that allows functional components to use React features such as state, context, and effects. Hook names begin with the word use, such as useState, useEffect, and useContext.

The useState Hook specifically provides state management for functional components.

Examples of React Hooks

Hook Purpose
useState Stores and updates component state.
useEffect Synchronizes a component with external systems.
useContext Reads values from React Context.
useRef Stores a value or references a DOM element without triggering a render when the ref changes.
useReducer Manages state through a reducer function.

3. Why Do We Need the useState Hook?

Regular JavaScript variables are not sufficient when a component needs to remember a value between renders and display changes automatically. Changing a local variable does not tell React to render the component again.

The useState Hook solves this problem by providing:

  • A state value that React remembers between renders.
  • A setter function to request a state update.
  • A way to keep the displayed UI synchronized with the latest state.

Example Without useState

function Counter() {
  let count = 0;
  function increase() {
    count = count + 1;
  }
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={increase}>Increase</button>
    </div>
  );
}

This example does not work as intended. Changing count does not trigger a render, and a later render initializes the local variable again.

Example With useState

import { useState } from "react";
function Counter() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increase
      </button>
    </div>
  );
}

Here, React remembers count between renders and updates the displayed value when setCount is called.


4. Syntax of the useState Hook

General Syntax

const [state, setState] = useState(initialState);

Explanation of each part:

  • state: The current state value available during the current render.
  • setState: The function used to request a state update.
  • useState(): The React Hook that declares a state variable.
  • initialState: The value used to initialize state during the component's first render.
  • []: JavaScript array destructuring is used to assign the two returned values to separate variables.

Example

import { useState } from "react";
function App() {
  const [name, setName] = useState("Rahul");
  return <h2>Name: {name}</h2>;
}
export default App;

The name state starts with Rahul. The setName function can request a different value when needed.


5. Understanding the Two Values Returned by useState

The useState Hook returns an array containing two values.

5.1 Current State Value

The first value is the current state. It can be displayed in JSX or used in calculations.

const [count, setCount] = useState(0);
<p>Current Count: {count}</p>

5.2 State Setter Function

The second value is a function used to request the next state value.

setCount(count + 1);

When the setter is called, React schedules a state update and renders the component again when necessary.


6. Initializing State with Different Data Types

The useState Hook can store different JavaScript data types depending on the information the component needs to remember.

6.1 Number State

const [age, setAge] = useState(25);

Useful for counters, quantities, scores, and ratings.

6.2 String State

const [name, setName] = useState("Amit");

Useful for names, messages, search queries, and text inputs.

6.3 Boolean State

const [isVisible, setIsVisible] = useState(false);

Useful for showing or hiding content, opening menus, and tracking enabled or disabled options.

6.4 Array State

const [skills, setSkills] = useState(["HTML", "CSS", "React"]);

Useful for lists of tasks, products, students, or selected items.

6.5 Object State

const [user, setUser] = useState({
  name: "Aarav",
  city: "Mumbai"
});

Useful for related information such as profile details and form data.


7. Updating State Using the Setter Function

To update state, call the setter function returned by useState. Do not assign a new value directly to the state variable.

Example

import { useState } from "react";
function NameChanger() {
  const [name, setName] = useState("Amit");
  return (
    <div>
      <h2>{name}</h2>
      <button onClick={() => setName("Priya")}>
        Change Name
      </button>
    </div>
  );
}
export default NameChanger;

Initially, the heading displays Amit. Clicking the button requests an update to Priya.

Important Point

A setter does not change the state variable in the currently executing render. State behaves like a snapshot for that render. The updated value becomes available when React renders the component again.


8. Updating State Based on the Previous State

When a new state value depends on the previous value, use the functional updater form. This is particularly useful when multiple state updates are queued.

Syntax

setCount(previousCount => previousCount + 1);

Example: Increase Count by Three

import { useState } from "react";
function Counter() {
  const [count, setCount] = useState(0);
  function increaseByThree() {
    setCount(previousCount => previousCount + 1);
    setCount(previousCount => previousCount + 1);
    setCount(previousCount => previousCount + 1);
  }
  return (
    <div>
      <h2>Count: {count}</h2>
      <button onClick={increaseByThree}>Increase by 3</button>
    </div>
  );
}
export default Counter;

Each updater receives the pending previous value and calculates the next value. Clicking the button increases the count by three.


9. Using Multiple useState Hooks

A functional component can use multiple useState Hooks to manage separate pieces of information. This is useful when each value has its own purpose or update behavior.

Example

import { useState } from "react";
function Profile() {
  const [name, setName] = useState("Neha");
  const [age, setAge] = useState(22);
  const [city, setCity] = useState("Mumbai");
  return (
    <div>
      <p>Name: {name}</p>
      <p>Age: {age}</p>
      <p>City: {city}</p>
      <button onClick={() => setName("Riya")}>Change Name</button>
      <button onClick={() => setAge(age + 1)}>Increase Age</button>
      <button onClick={() => setCity("Pune")}>Change City</button>
    </div>
  );
}
export default Profile;

Each state variable stores a separate value, and its corresponding setter updates that value.


10. Lazy Initialization with useState

If calculating the initial state is expensive, you can pass an initializer function to useState. React calls the initializer to calculate the initial value during initialization rather than treating its result as an ordinary value on every render.

Example

import { useState } from "react";
function createInitialCount() {
  console.log("Calculating initial count");
  return 10;
}
function Counter() {
  const [count, setCount] = useState(createInitialCount);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increase</button>
    </div>
  );
}
export default Counter;

Notice that the function is passed as useState(createInitialCount), not called as useState(createInitialCount()). In development Strict Mode, React may call initializer functions more than once to help identify unintended side effects, so initializers should be pure.


11. Updating Object State Correctly

Objects stored in state should be treated as read-only. Create a new object with the changed property instead of modifying the existing object.

Example

import { useState } from "react";
function UserProfile() {
  const [user, setUser] = useState({
    name: "Aarav",
    city: "Mumbai"
  });
  function changeCity() {
    setUser(previousUser => ({
      ...previousUser,
      city: "Pune"
    }));
  }
  return (
    <div>
      <p>Name: {user.name}</p>
      <p>City: {user.city}</p>
      <button onClick={changeCity}>Change City</button>
    </div>
  );
}
export default UserProfile;

The spread syntax copies the existing properties, while city is updated in the new object.


12. Updating Array State Correctly

When updating an array in state, create a new array instead of modifying the existing array directly.

Example: Adding an Item

import { useState } from "react";
function TodoList() {
  const [todos, setTodos] = useState(["Learn HTML", "Learn CSS"]);
  function addTodo() {
    setTodos(previousTodos => [...previousTodos, "Learn React"]);
  }
  return (
    <div>
      <ul>
        {todos.map(todo => (
          <li key={todo}>{todo}</li>
        ))}
      </ul>
      <button onClick={addTodo}>Add Task</button>
    </div>
  );
}
export default TodoList;

The spread syntax copies the previous items into a new array and adds Learn React to the end.


13. Using useState with Event Handling

State is frequently updated in response to events such as button clicks, form submissions, text input, and checkbox changes.

Example: Toggle Message Visibility

import { useState } from "react";
function ToggleMessage() {
  const [isVisible, setIsVisible] = useState(false);
  return (
    <div>
      <button onClick={() => setIsVisible(previous => !previous)}>
        {isVisible ? "Hide Message" : "Show Message"}
      </button>
      {isVisible && <p>Welcome to React JS!</p>}
    </div>
  );
}
export default ToggleMessage;

The button toggles isVisible between true and false. The message is rendered only when isVisible is true.


14. Using useState with Form Inputs

The useState Hook can manage form data. In a controlled input, the value attribute reads from state, and the onChange handler updates state whenever the user types.

Example

import { useState } from "react";
function NameForm() {
  const [name, setName] = useState("");
  return (
    <div>
      <label htmlFor="name">Enter your name: </label>
      <input
        id="name"
        value={name}
        onChange={event => setName(event.target.value)}
      />
      <p>Your name is: {name}</p>
    </div>
  );
}
export default NameForm;

Every change to the input updates name state, and the paragraph displays the current value.


15. Rules of Using the useState Hook

  • Call useState at the top level of a functional component or custom Hook.
  • Do not call useState inside conditions, loops, or nested functions.
  • Call state setters to request updates instead of assigning to state variables.
  • Treat arrays and objects in state as read-only.
  • Use functional updater syntax when the next value depends on the previous value.
  • Keep state variables clear and meaningful.
  • Keep initializer functions pure and free of side effects.

16. Common Mistakes When Using useState

Mistake Why It Is a Problem Correct Approach
Changing a regular variable It does not trigger a React render. Use useState for information the UI must remember.
Assigning directly to state It does not correctly request a state update. Use the setter function.
Mutating an object or array It can cause inconsistent UI behavior. Create a new object or array.
Expecting immediate state changes The current render keeps its existing state snapshot. Use the updated value on a subsequent render.
Calling useState conditionally It violates the Rules of Hooks. Call Hooks unconditionally at the top level.
Passing a function when you intend to store a function A function passed to useState is treated as an initializer. To store a function itself, use a lazy initializer that returns it, such as useState(() => myFunction).

17. Difference Between useState and Regular Variables

Feature Regular Variable useState
Remembers values between renders No, local variables are recreated when the component function runs. Yes, React preserves the state value.
Triggers a render when changed No. Calling the setter requests an update.
Best use Temporary calculations within a render. Values that affect the UI and must persist.
Example let count = 0; const [count, setCount] = useState(0);

18. Difference Between Props and useState

Feature Props useState
Purpose Pass information into a component. Manage information a component needs to remember.
Source Usually supplied by a parent. Declared inside the component or state-owning component.
Updating The parent supplies new prop values. The setter requests a state update.
Example const [name, setName] = useState("Riya");

19. Practical Project: Counter Application

Objective: Build a counter using useState with Increase, Decrease, and Reset buttons.

App.jsx

import { useState } from "react";
function App() {
  const [count, setCount] = useState(0);
  return (
    <div>
      <h1>Counter Application</h1>
      <h2>Count: {count}</h2>
      <button onClick={() => setCount(previous => previous + 1)}>Increase</button>
      <button onClick={() => setCount(previous => previous - 1)}>Decrease</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}
export default App;

Project Outcome: The count is stored in state. The buttons update it, and React displays the latest value after each update.


20. Interview Questions and Answers

Q1. What is the useState Hook?

useState is a built-in React Hook that lets functional components declare and update state variables.

Q2. What does useState return?

It returns an array containing the current state value and a setter function.

Q3. What is the purpose of the initial state?

It specifies the state value used during the component's initial render.

Q4. Can a component use multiple useState Hooks?

Yes. A component can use multiple state variables to manage separate pieces of information.

Q5. Why does React re-render after a state update?

React needs to render the component with the updated state so the UI can reflect the latest information.

Q6. Why should state not be modified directly?

State should be treated as read-only. Use the setter and create new objects or arrays when updating structured state.

Q7. When should functional updater syntax be used?

Use it when the next state depends on the previous state, such as incrementing a counter.

Q8. Can useState store objects and arrays?

Yes. It can store any JavaScript value, including objects and arrays.

Q9. What are the Rules of Hooks?

Hooks must be called at the top level of React components or custom Hooks, not inside conditions, loops, or nested functions.

Q10. What is lazy initialization?

Lazy initialization passes a function to useState so React can call it to calculate the initial state.


21. Practice Exercises

  1. Create a counter that increases when a button is clicked.
  2. Create a button that changes a message using state.
  3. Build a show/hide message feature using boolean state.
  4. Create a form that stores and displays a user's name.
  5. Build a task list that adds new tasks using array state.
  6. Create a profile that updates a city stored in object state.
  7. Build a Like button that toggles between Like and Liked.
  8. Create a counter with Increase, Decrease, and Reset buttons.
  9. Use a functional updater to increase a counter by three in one click.
  10. Create a component that uses multiple state variables for name and age.

22. Best Practices for Using useState

  • Use descriptive state variable and setter names.
  • Keep state as simple as possible.
  • Use state for information that must persist between renders and affect the UI.
  • Calculate values from existing props or state when storing them separately is unnecessary.
  • Use functional updater syntax when the next state depends on the previous state.
  • Create new objects and arrays instead of mutating existing state.
  • Use lazy initialization for expensive initial calculations.
  • Keep state in the component that needs to own and coordinate it.

23. Quick Revision Checklist

  • Understand what a React Hook is.
  • Know how to import useState.
  • Understand the syntax and returned values of useState.
  • Practice storing numbers, strings, booleans, arrays, and objects.
  • Know how to update state with a setter function.
  • Understand functional updater syntax.
  • Know how to update arrays and objects without mutation.
  • Understand the Rules of Hooks.
  • Practice creating interactive components.

24. Useful Learning Resources


25. Conclusion

The useState Hook is an essential React feature for building interactive applications. It allows functional components to remember information between renders and update the UI when state changes. Understanding state initialization, setter functions, functional updates, and safe handling of arrays and objects helps developers write reliable and maintainable React code.

Explore React JS Training: JustAcademy React JS Training Course

Register for a Course Demo: Register for React JS Course Demo

whatsapp